package org.abio.XasML.reflect
{
	import flash.utils.Dictionary;
	
	internal class MetadataAware
	{
		public function MetadataAware()
		{
		}

		static private var attributeDist:Dictionary=new Dictionary();
		static internal function register(attribute:Class):void{
			if(MetadataAware.attributeDist.hasOwnProperty('metadata')==false){
				var tempMetadataRegister:MetadataRegister=new MetadataRegister();
				tempMetadataRegister.Defination=MetadataRegister;
				MetadataAware.attributeDist['metadata']=tempMetadataRegister;
			}
			var metadataRegister:MetadataRegister=ClassInfo.of(attribute).getMetadata('metadata') as MetadataRegister;
			if(metadataRegister!=null){
				metadataRegister.Defination=attribute
				MetadataAware.attributeDist[metadataRegister.name]=metadataRegister;
			}
		}

		internal var metadata:Array=new Array();
		internal function get _raw_metadatas():Array{
			return this.metadata;
		}
		
		public function get metadatas():Array{
			var result:Array=new Array();
			for each(var metadata:MetadataInfo in this._raw_metadatas){
				result.push(this._getInstance(metadata));
			}
			return result;
		}

		public function getMetadata(name:String):Object{
			return this._getInstance(this._raw_metadatas.filter(function filter(element:MetadataInfo, index:int, arr:Array):Boolean{
				return element.Name==name;
			})[0] as MetadataInfo);
		}
		
		private function _getInstance(metadata:MetadataInfo):Object{
			if(metadata!=null && MetadataAware.attributeDist.hasOwnProperty(metadata.name)){
				var tempMetadataRegister:MetadataRegister=(MetadataAware.attributeDist[metadata.name] as MetadataRegister);
				if( (tempMetadataRegister.type==null || tempMetadataRegister.type=='' || tempMetadataRegister.type=='all')
					|| (tempMetadataRegister.type=='member' && (this is MethodInfo || this is PropertyInfo))
					|| (tempMetadataRegister.type=='class' && this is Factory)
					|| (tempMetadataRegister.type=='method' && this is MethodInfo)
					|| (tempMetadataRegister.type=='property' && this is PropertyInfo)
				){
					var result:Object=new tempMetadataRegister.defination();
					for each(var arg:ArgInfo in metadata.args){
						result[arg.Key]=arg.Value;
					}
					return result;
				}
			}
			return metadata;
		}
	}
}

class MetadataRegister
{
	public function MetadataRegister()
	{
	}

	internal var name:String=null;
	internal var type:String=null;
	
	internal var Defination:Class=null;
	internal function get defination():Class{	return this.Defination;}
}
